﻿using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Text;

namespace SharePointOnlineCmdlets
{
    /// <summary>
    /// Adds a user/group as a site collection administrator
    /// </summary>
    [Cmdlet(VerbsCommon.Add, "SPOSiteCollectionAdmin")]
    public class AddSPOSiteCollectionAdmin : PSCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public Site Site { get; set; }

        [Parameter(Mandatory = true)]
        public string UserOrGroup { get; set; }

        protected override void ProcessRecord()
        {
            var userOrGroup = Site.RootWeb.EnsureUser(UserOrGroup);
            userOrGroup.IsSiteAdmin = true;
            userOrGroup.Update();
            Site.Context.Load(userOrGroup);
            Site.Context.ExecuteQuery();
        }
    }

    /// <summary>
    /// Adds a new Permission Level (RoleDefinition) to a Web
    /// </summary>
    [Cmdlet(VerbsCommon.New, "SPOPermissionLevel")]
    public class NewSPOPermissionLevel : PSCmdlet
    {
        [Parameter(ValueFromPipeline = true), ValidateNotNullOrEmpty]
        public Web Web { get; set; }

        [Parameter(Mandatory = true)]
        public string Name { get; set; }

        [Parameter]
        public string Description { get; set; }

        [Parameter]
        public string Permissions { get; set; }


        protected override void ProcessRecord()
        {
            var basePermissions = new BasePermissions();
            foreach (var permission in Permissions.Split(';'))
            {
                var permType = PermissionKind.EmptyMask;
                Enum.TryParse<PermissionKind>(permission, out permType);
                basePermissions.Set(permType);
            }
            Web.RoleDefinitions.Add(new RoleDefinitionCreationInformation(){ BasePermissions = basePermissions, Name = Name, Description = Description });
            Web.Context.ExecuteQuery();
        }
    }

    /// <summary>
    /// Returns an array of Permission Kinds which can be used to create a permission level.
    /// </summary>
    [Cmdlet(VerbsCommon.Get, "SPOPermissionKinds")]
    public class GetSPOPermissionKinds : PSCmdlet
    {
        protected override void ProcessRecord()
        {
            WriteObject(Enum.GetNames(typeof(PermissionKind)));
        }
    }

    /// <summary>
    /// Gets all groups under a web
    /// </summary>
    [Cmdlet(VerbsCommon.Get, "SPOGroups")]
    public class GetSPOGroups : PSCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public Web Web { get; set; }

        protected override void ProcessRecord()
        {
            Web.Context.Load(Web.SiteGroups);
            Web.Context.ExecuteQuery();
            WriteObject(Web.SiteGroups);
        }
    }

    /// <summary>
    /// Adds a user to a group
    /// </summary>
    [Cmdlet(VerbsCommon.Add, "SPOUserToGroup")]
    public class AddSPOUserGroup : PSCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public Web Web { get; set; }

        [Parameter(Mandatory = true)]
        public string UserName { get; set; }

        [Parameter(Mandatory = true)]
        public string GroupName { get; set; }

        protected override void ProcessRecord()
        {
            var user = Web.EnsureUser(UserName);
            Web.Context.Load(Web.SiteGroups);
            Web.Context.ExecuteQuery();
            var group = Web.SiteGroups.FirstOrDefault(g => g.Title.ToLowerInvariant() == GroupName.ToLowerInvariant());
            Web.Context.Load(user);
            Web.Context.ExecuteQuery();
            group.Users.AddUser(user);
            Web.Context.ExecuteQuery();
            WriteObject(Web);
        }
    }

    /// <summary>
    /// Gets all users under a web
    /// </summary>
    [Cmdlet(VerbsCommon.Get, "SPOWebUsers")]
    public class GetSPOWebUsers : PSCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public Web Web { get; set; }

        protected override void ProcessRecord()
        {  
            Web.Context.Load(Web.SiteUsers);
            Web.Context.ExecuteQuery();
            WriteObject(Web.SiteUsers);
        }
    }

    /// <summary>
    /// Creates a new SharePoint group optionally adding a permission level.
    /// </summary>
    [Cmdlet(VerbsCommon.New, "SPOGroup")]
    public class NewSPOGroup : PSCmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public Web Web { get; set; }

        [Parameter(Mandatory = true)]
        public string Name { get; set; }

        [Parameter]
        public string Description { get; set; }

        [Parameter]
        public string PermissionLevel { get; set; }

        protected override void ProcessRecord()
        {
            Web.SiteGroups.Add(new GroupCreationInformation() { Title = Name, Description = Description });
            Web.Context.ExecuteQuery();
            if (!String.IsNullOrEmpty(PermissionLevel))
            {
                var group = Web.SiteGroups.GetByName(Name);
                var role = Web.RoleDefinitions.GetByName(PermissionLevel);
                Web.Context.Load(group);
                Web.Context.Load(role);
                Web.Context.ExecuteQuery();
                var roleBinding = new RoleDefinitionBindingCollection(Web.Context) {role};
                Web.RoleAssignments.Add(group, roleBinding);
                Web.Context.ExecuteQuery();
            }
        }
    }
}
